<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>[1.13]-统一的接口请求方式：_sevice=XXX.XXX | PhalApi(π框架) - PHP轻量级开源接口框架 - 助你创造价值！</title>
    <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
    <meta content="yes" name="apple-mobile-web-app-capable">
    <meta content="black" name="apple-mobile-web-app-status-bar-style">
    <meta content="telephone=no" name="format-detection">
    <meta content="email=no" name="format-detection">
    <meta name="Author" content="PhalApi,ecitlm,dogstar">
    <meta name="description" content="[1.13]-统一的接口请求方式：_sevice=XXX.XXX，PhalApi是一个PHP轻量级开源接口框架，致力于快速开发接口服务。支持HTTP/SOAP/RPC等协议，可用于搭建接口/微服务/RESTful接口/Web Services。我们不断更新，保持生气；为接口负责，为开源负责！并承诺永久免费！">
    <meta name="keywords" content="PhalApi,phalapi,phalapi接口开发,后台接口开发,后台接口开发框架,接口开发,接口框架,开源接口框架,PHP后台接口开发,PHP接口开发,PHP接口框架,PHP后台接口框架,phalapi官网,PHP接口框架,php接口开发框架,php接口开发,php web框架,π框架,π开发框架,π接口框架,π接口开发框架,api接口,php接口,,PHP接口框架,phalapi文档,phalapi wiki,PhalApi文档,phalapi在线文档,phalapi官方文档">

    <link rel="stylesheet" type="text/css" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" media="screen">
    <link rel="stylesheet" type="text/css" href="https://cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.css" media="screen">
    <link rel="stylesheet" href="../css/main.css" />
    <link rel="stylesheet" href="../css/loading_bar.css" />
    <link rel="icon" href="http://webtools.qiniudn.com/dog_catch.png" type="image/x-icon" />
    <script src="../js/pace.min.js"></script>
	
	<!-- 代码高亮 -->
	<link rel="stylesheet" href="../css/highlight.min.css">
	<script src="../js/highlight.min.js"></script>
	<script>hljs.initHighlightingOnLoad();</script>
    
</head>

<body>
    <!-- navbar start -->
    <div class="navbar navbar-default navbar-fixed-top" id="mainnav" role="navigation">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a class="navbar-brand website_name" href="/"><!-- <span>PhalApi</span> --><strong></strong></a>
            </div>
            <div class="navbar-collapse collapse" aria-expanded="false" style="height: 1px;">
                <ul class="nav navbar-nav navbar-right" id="nav_bar">
                    <li><a href="https://www.phalapi.net/"><span class="glyphicon glyphicon-home"></span></a></li>
                    <li><a href="https://www.phalapi.net/download.html">下载</a></li>
                    <li class="active"><a href="https://www.phalapi.net/wikis/">文档</a></li>
                    <li><a href="https://www.phalapi.net/donate.html">贡献</a></li>
                    <li><a href="#">|</a></li>
                    <li><a href="http://qa.phalapi.net/" target="_blank">社区</a></li>
                    <li><a href="http://www.ituring.com.cn/book/2405" target="_blank">书籍</a></li>
                    <li><a href="http://demo.phalapi.net/listAllApis.php" target="_blank">体验</a></li>
                    <li><a href="https://github.com/phalapi/phalapi-library" target="_blank">扩展</a></li>
                </ul>
            </div>
            <!--/.nav-collapse -->
        </div>
    </div>
    <!-- navbar end -->


    <div id="content">
        <div class="container">
            <div class="row row-md-flex row-md-flex-wrap">
                <h4><a href="/wikis/%5B1.12%5D-%E5%8F%82%E6%95%B0%E8%A7%84%E5%88%99%EF%BC%9A%E6%8E%A5%E5%8F%A3%E5%8F%82%E6%95%B0%E8%A7%84%E5%88%99%E9%85%8D%E7%BD%AE.html">上一章</a>   <a href="/wikis/">文档首页</a>   <a href="/wikis/%5B1.14%5D-%E7%BB%9F%E4%B8%80%E7%9A%84%E8%BF%94%E5%9B%9E%E6%A0%BC%E5%BC%8F%E5%92%8C%E7%BB%93%E6%9E%84%EF%BC%9Aret-data-msg.html">下一章</a></h4>
<hr />
<p><em>有句话说得好，最可怕的事情不是别人比你优秀，而是优秀的人竟然还比你更努力。  --《考拉小巫的留学成长日记》</em>  </p>
<p>此篇章主要是讲述接口统一请求的方式，以及提供一个PHP实现的简单客户端。</p>
<h2>1.13.1 指定接口服务：?service=XXX.XXX</h2>
<p>我们统一固定用service参数来表示需要请求获得的服务，并通过GET方式传递，即请求的URI格式为：</p>
<pre><code>接口域名 + 入口路径 + ?service=XXX.XXX

如：
http://dev.phalapi.com   +   /demo/  +  ?service=User.GetBaseInfo</code></pre>
<p>当我们在浏览器以GET方式请求时，可以在nignx看到这样的日记：</p>
<pre><code class="language-php">127.0.0.1 - - [07/Feb/2015:22:46:46 -0800] "GET /demo/?service=User.GetBaseInfo&amp;sign=&amp;user_id=1 HTTP/1.1" 200 107 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:11.0) Gecko/20100101 Firefox/11.0"</code></pre>
<p>如果通过接口用POST方式请求，则会看到：</p>
<pre><code class="language-php">127.0.0.1 - - [07/Feb/2015:19:32:05 -0800] "POST /demo/?service=User.GetBaseInfo&amp;sign= HTTP/1.1" 200 135 "-" "-"</code></pre>
<p>这里service的名称，开头不区分大小写，建议统一以大写开头，以显得专业。对应的接口是：</p>
<pre><code class="language-php">class Api_User extends PhalApi_Api {

    public function getBaseInfo() {
    }
}</code></pre>
<h3>其他传递接口服务名称的方式</h3>
<p>虽然在这里，我们统一使用<code>?service=XXX.XXX</code>的格式来传递接口服务名称，但如果项目有需要，也可以采用其他方式来传递，如使用熟悉的斜杠分割：<code>?service=XXX/XXX</code>，或者使用省略方法名的方式而在服务端自动补全默认方法，又或者使用其他参数名称，如使用<code>?s=XXX.XXX</code>。  </p>
<p>如果需要采用其他传递接口服务名称的方式，则可以重载<code>PhalApi_Request::getService()</code>方法。以下是改用斜杠分割、并换用<code>r</code>参数名字的实现示例：  </p>
<pre><code class="language-php">&lt;?php
class Common_Request extends PhalApi_Request {

    public function getService() {
        // 优先返回自定义格式的接口服务名称
        $servcie = $this-&gt;get('r');
        if (!empty($servcie)) {
            return str_replace('/', '.', $servcie);
        } 

        return parent::getService();
    }
}</code></pre>
<p>实现好自定义的请求类，需要在入口文件<code>./Public/项目/index.php</code>进行注册：  </p>
<pre><code class="language-php">//装载你的接口
DI()-&gt;loader-&gt;addDirs('Demo');

DI()-&gt;request = new Common_Request();</code></pre>
<p>这样，请求接口服务的方式便可以变成这样了。  </p>
<table class="table table-bordered">
<thead>
<tr>
<th>原来的方式</th>
<th>现在的方式</th>
</tr>
</thead>
<tbody>
<tr>
<td>?service=Default.Index</td>
<td>?r=Default/Index</td>
</tr>
<tr>
<td>?servcie=User.GetBaseInfo</td>
<td>?r=User/GetBaseInfo</td>
</tr>
</tbody>
</table>
<p>这里有几个注意事项：  </p>
<ul>
<li>1、需要转换为原始的接口服务格式，即：XXX.XXX  </li>
<li>2、为保持兼容性，子类需兼容父类的实现。即在取不到自定义的接口服务名称参数时，应该返回原来的。  </li>
</ul>
<blockquote>
<p>温馨提示：以上定制功能，需要PhalApi 1.4.0及以上版本，方可支持。  </p>
</blockquote>
<h2>1.13.2 统一参数用GET</h2>
<p>在一个项目中，会有很多公共的接口参数，如客户端、版本号、密钥等。这些同样可以纳入GET参数里面，或者也可以放到POST里面。  </p>
<blockquote>
<p>温馨提示：<br />
这样要求是有目的的，因为这样的话可以在nginx的access日记里面查看来自客户端的快照信息，以便统计或者定位问题。  </p>
</blockquote>
<h2>1.13.3 接口参数用POST</h2>
<p>特别地，接口参数我们建议统一使用POST方式传递，理由很简单：  </p>
<ul>
<li>1、相对保护上传的数据，一如密码；</li>
<li>2、避免特殊字符或者过大数据包在GET下的限制；</li>
</ul>
<h2>1.13.4 获取Header头信息</h2>
<p>每个请求都有自己的Header头,获取Header头信息可以判断请求来源或者是把一些敏感的内容存放到Header头信息中(如:加密后的参数),框架也提供了方便快捷获取Header的方法:</p>
<pre><code class="language-php">DI()-&gt;request-&gt;getHeader("Host");</code></pre>
<h2>1.13.5 测试下的模拟参数</h2>
<p>默认地，PhalApi框架会将$_REQUEST作为接口参数的来源：</p>
<pre><code class="language-php">DI()-&gt;request = 'PhalApi_Request';</code></pre>
<p>当我们需要统一强制用$_GET，可以在init.php文件中这样简单定制：</p>
<pre><code class="language-php">DI()-&gt;request = new PhalApi_Request($_GET);</code></pre>
<p>同样，也可以在init.php文件中强制用$_POST：</p>
<pre><code class="language-php">DI()-&gt;request = new PhalApi_Request($_POST);</code></pre>
<p>在测试环境下，为了模拟接口请求，我们需要人工提供接口参数，因此可以这样轻松模拟：</p>
<pre><code class="language-php">$str = 'service=User.GetBaseInfo&amp;user_id=1';

parse_str($str, $params);
DI()-&gt;request = new PhalApi_Request($params);</code></pre>
<h2>1.13.6 PHP接口客户端示例</h2>
<p>先看下调用和使用的代码示例：</p>
<pre><code class="language-php">&lt;?php
require_once './PhalApiClient.php';

$config = array(
    'host' =&gt; 'http://dev.phalapi.com/demo',
    'secrect' =&gt; '******'
);

$client = new PhalApiClient($config);
$rs = $client-&gt;request('User.GetBaseInfo', array('userId' =&gt; 1));

if ($client-&gt;getRet() == PhalApiClient::RET_OK) {
    var_dump($rs);
} else {
    var_dump($client-&gt;getMsg());
    var_dump($client-&gt;getUrl());
}</code></pre>
<p>附调用接口的客户端源代码：</p>
<pre><code class="language-php">//$ vim ./PhalApiClient.php
&lt;?php

class PhalApiClient
{
    protected $host;
    protected $secrect = '';

    protected $params = array();

    protected $moreParams = array();

    protected $url;
    protected $ret;
    protected $msg;
    protected $data = array();

    const RET_OK = 'OK';
    const RET_WRONG = 'WRONG';
    const RET_ERROR = 'ERROR';

    public function __construct($config)
    {
        $this-&gt;host = rtrim($config['host'], '/') . '/';
        $this-&gt;secrect = $config['secrect'];
    }

    public function request($service, $params = array(), $timeoutMs = 3000)
    {
        if (!empty($service)) {
            $this-&gt;params['service'] = $service;
        }
        $this-&gt;params['sign'] = $this-&gt;encryptAppKey($params, $this-&gt;secrect);
        $this-&gt;url = $this-&gt;host . '?' . http_build_query($this-&gt;params);
        $this-&gt;moreParams = $params;

        $rs = $this-&gt;doRequest($this-&gt;url, $params, $timeoutMs);

        if ($rs === false) {
            $this-&gt;ret = self::RET_ERROR;
            $this-&gt;msg = '后台接口请求超时';
            return $this-&gt;getData();
        }

        $rs = json_decode($rs, true);

        if (isset($rs['data']['code']) &amp;&amp; $rs['data']['code'] != 0) {
            $this-&gt;ret = self::RET_WRONG;
            $this-&gt;msg = '接口调用失败[code =' . $rs['data']['code'] . ']' . ', 错误&gt;信息：' . isset($rs['data']['msg']) ? $rs['data']['msg'] : '无';
            return $this-&gt;getData();
        }

        $this-&gt;ret = intval($rs['ret']) == 200 ? self::RET_OK : self::RET_WRONG;
        $this-&gt;data = $rs['data'];
        $this-&gt;msg = $rs['msg'];

        return $this-&gt;getData();
    }

    public function getRet()
    {
        return $this-&gt;ret;
    }

    public function getData()
    {
        return $this-&gt;data;
    }

    public function getMsg()
    {
        return $this-&gt;msg;
    }

    public function getUrl()
    {
        return $this-&gt;url . '&amp;' . http_build_query($this-&gt;moreParams);
    }

    protected function encryptAppKey($params, $secrect)
    {
        return '';
    }

    protected function doRequest($url, $data, $timeoutMs = 3000)
    {
        $ch = curl_init();

        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS, $timeoutMs);

        if (!empty($data)) {
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        }

        $rs = curl_exec($ch);

        curl_close($ch);

        return $rs;
    }
}</code></pre>
<hr />
<h4><a href="/wikis/%5B1.12%5D-%E5%8F%82%E6%95%B0%E8%A7%84%E5%88%99%EF%BC%9A%E6%8E%A5%E5%8F%A3%E5%8F%82%E6%95%B0%E8%A7%84%E5%88%99%E9%85%8D%E7%BD%AE.html">上一章</a>   <a href="/wikis/">文档首页</a>   <a href="/wikis/%5B1.14%5D-%E7%BB%9F%E4%B8%80%E7%9A%84%E8%BF%94%E5%9B%9E%E6%A0%BC%E5%BC%8F%E5%92%8C%E7%BB%93%E6%9E%84%EF%BC%9Aret-data-msg.html">下一章</a></h4><div style="float: left">
<h4>
<a href="http://qa.phalapi.net/">还有疑问？欢迎到社区提问！</a>
&nbsp;&nbsp;
<a href="http://docs.phalapi.net/#/v2.0/">切换到PhalApi 2.x 开发文档。</a>
</h4>
</div>
            </div>
        </div>
    </div>

 <!-- 广告位 -->
<div class="grid-wrapper desktop-only">
	<p align="center">
		<a href="http://7xiz2f.com1.z0.glb.clouddn.com/%E6%88%91%E7%9A%84%E5%90%8D%E5%AD%97%E5%8F%AB%EF%BC%9A%CF%80%E6%A1%86%E6%9E%B6%20-%20PhalApi%202016%E5%B9%B4%E5%BA%A6%E5%BC%80%E6%BA%90%E6%80%BB%E7%BB%93%20-%20%E5%AE%98%E6%96%B9%E5%87%BA%E5%93%81.pdf" target="blank"><img width="950" height="100" src="http://7xiz2f.com1.z0.glb.clouddn.com/ad_20170104.png"></a>
		<a href="http://www.itran.cc/" target="blank"><img width="950" height="100" src="http://7xslqv.com1.z0.glb.clouddn.com/images/9/69/b88bc92455dc1239f9a5bf8d72929.png"></a>
		<a href="http://web-tools.phalapi.net/" target="blank"><img width="950" height="100" src="http://7xslqv.com1.z0.glb.clouddn.com/images/7/d0/88f523566c482296aecc43d185ca2.png"></a>
	</p>
</div>

        <!-- footer -->
        <div class="footer">
            <div class="link container ">
                <div class=" col-xs-7 col-sm-7 col-md-7 col-lg-7 ">
                    <h3>PhalApi (π框架)</h3>
                    <p>一个轻量级PHP开源接口框架，专注于接口服务开发，支持HTTP/SOAP/RPC协议，拥有自动生成的在线文档、多种开发语言的客户端SDK包以及可重用的扩展类库，可用于快速搭建微服务、RESTful接口或Web
                        Services。</p>
                    <!-- <p>:</p> -->
                    <a href="https://www.phalapi.net/" target="_blank"> PhalApi </a>
                    <span>|</span>
                    <a href="http://qa.phalapi.net/" target="_blank">社区</a>
                    <span>|</span>
                    <a href="download.html" target="_blank">下载</a>
                    <span>|</span>
                    <a href="/wikis/">文档</a>
                    <span>|</span>
                    <a href="http://www.ituring.com.cn/book/2405" target="_blank">书籍</a>
                    <span>|</span>
                    <a href="http://demo.phalapi.net/listAllApis.php" target="_blank">体验</a>
                    <span>|</span>
                    <a href="donate.html" target="_blank">贡献</a>
                    <span>|</span>
                    <a href="https://github.com/phalapi/phalapi-library" target="_blank">扩展</a>
                    <span>|</span>
                    <a href="/license.html" target="_blank">许可</a>
                    <span>|</span>
                    <a href="/about.html" target="_blank">关于</a>
                    <span>|</span>
                    <a href="https://www.phalapi.net/wikis/en/" target="_blank">English</a>

                </div>
                <div class=" col-xs-5 col-sm-5 col-md-5 col-lg-5 contact_us ">
                    <h3>联系我们</h3>
                    <a href="https://github.com/phalapi/phalapi"><img src="../images/github.png" alt="github" /></a>
                    <a href="http://weibo.com/p/100808d236e99beb645bfb56ed1c37dde9b8bd?k=phalapi%E5%BC%80%E6%BA%90%E6%A1%86%E6%9E%B6&from=501&_from_=huati_topic"><img src="../images/weibo.png"  alt="weibo" /></a>
                    <a href="http://7xslqv.com1.z0.glb.clouddn.com/images/1/b0/894fde762850cb11250253f7d5ede.png"><img src="../images/zfb.png"  alt="zfb" /></a>
					<a target="_blank" href="//shang.qq.com/wpa/qunwpa?idkey=f16292029e59975d4ccfccc70ed87aa5c5646df512e83b0e9e1270e8368be461"><img border="0" src="images/qq.png" alt="π框架 - PhalApi交流群②" title="π框架 - PhalApi交流群②"></a>
					<a href="http://git.oschina.net/dogstar/PhalApi"><img src="../images/git-oschina.png"  alt="git-oschina" /></a>
                </div>
                <div class="cls"></div>
                <div class="text-center copy_right"> ©2015-2017 PhalApi All Rights Reserved. <a href="http://www.miitbeian.gov.cn" target="_blank">粤ICP备15028808号</a>

				<script type="text/javascript">var cnzz_protocol = (("https:" == document.location.protocol) ? " https://" : " http://");document.write(unescape("%3Cspan id='cnzz_stat_icon_1255326144'%3E%3C/span%3E%3Cscript src='" + cnzz_protocol + "s4.cnzz.com/z_stat.php%3Fid%3D1255326144%26show%3Dpic' type='text/javascript'%3E%3C/script%3E"));</script>
                </div>
            </div>
        </div>
    </div>


    <a href="https://github.com/phalapi"><img id="gitHub_fllow" style="position: fixed; top: 0; right: 0; border: 0;z-index:9999" src="https://camo.githubusercontent.com/652c5b9acfaddf3a9c326fa6bde407b87f7be0f4/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f6f72616e67655f6666373630302e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_orange_ff7600.png"></a>


    <script src="../js/jquery-1.11.1.min.js"></script>
    <script src="../js/bootstrap.min.js"></script>
</body>

</html>